package com.ybwh.springboot2.conf;

import com.ybwh.springboot2.common.BusinessException;
import com.ybwh.springboot2.common.RespData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * 全局异常处理
 *
 * @author Fan Beibei
 * @since 1.0-SNAPSHOT
 */
@Slf4j
@RestControllerAdvice
public class SpringbootExceptionHandler {

    /**
     * 处理参数异常
     *
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public RespData<Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e1) {

        return new RespData<Object>(RespData.FAIL_CODE,
                " miss parameters,name=[" + e1.getParameterName() + "],type=[" + e1.getParameterType() + "]", null);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
    public RespData<Object> handleMissingServletRequestParameterException(MethodArgumentTypeMismatchException e2) {
        return new RespData<>(RespData.FAIL_CODE, "param type  error,name=[" + e2.getName() + "], required type is[" + e2.getRequiredType()
                + "],actual value is [" + e2.getValue() + "].\n", null);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({TypeMismatchException.class})
    public RespData<Object> handleMissingServletRequestParameterException(TypeMismatchException e2) {
        return new RespData<>(RespData.FAIL_CODE, "property type  error,name=[" + e2.getPropertyName() + "], required type is[" + e2.getRequiredType()
                + "],actual value is [" + e2.getValue() + "].\n", null);
    }

    /**
     * 处理请求方式不支持异常
     *
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public RespData<Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {

        return new RespData<Object>(RespData.FAIL_CODE, "HTTP request type error!! required type is "
                + e.getSupportedHttpMethods() + ",but your type is " + e.getMethod(), null);
    }

    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public RespData<Object> handleNoHandlerFoundException(NoHandlerFoundException e) {
        return new RespData<Object>(RespData.FAIL_CODE,
                "404  url not found!!,request type is " + e.getHttpMethod() + ",url is " + e.getRequestURL(), null);
    }


    /**
     * 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RespData<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return new RespData<Object>(RespData.FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage(), null);
    }


    /**
     * 处理文件大小限制异常
     *
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(MultipartException.class)
    public RespData<Object> handleMultipartException(MultipartException e) {
        return new RespData<Object>(RespData.FAIL_CODE, "upload file erorr!! " + ExceptionUtils.getStackTrace(e), null);
    }


    /**
     * 处理其他异常
     *
     * @return
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(Throwable.class)
    public RespData<Object> handlePlatformException(Throwable e) {
        //抛出的业务异常
        if (e instanceof BusinessException) {
            return new RespData<Object>(RespData.FAIL_CODE, e.getMessage(), null);
        }

        log.error("系统异常,{}", ExceptionUtils.getStackTrace(e));
        return new RespData<Object>(RespData.FAIL_CODE, "系统异常,请联系管理员", null);
    }


}
